package com.sttg.csp.registration.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import com.sttg.csp.common.consts.SystemConst;
import com.sttg.csp.common.exception.BizException;
import com.sttg.csp.common.util.LDAPUtil;

public class BDUserRegDAO {

	private static final BDUserRegDAO instance = new BDUserRegDAO();   
	

	/** 
	 * Private the default constructor.
	 */   
	private BDUserRegDAO() {}    
   
	/** 
	 * Static factory methods.
	 */   
	public static BDUserRegDAO getInstance() {
		return instance;    
	}    
	
	/**
	 * Search a certificate detail.
	 * @param param
	 * @return
	 */
	public Map queryBDUserReg(Map param) throws BizException {
		String cerAssocCN = (String) param.get("CN");
		Map<String, String> each = new HashMap<String, String>();
		try {
			SearchControls controls = new SearchControls();
			controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
			Attributes attrs = LDAPUtil.getDirContext().getAttributes("cn=" + cerAssocCN + "," + LDAPUtil.BD_CER_ASSOC_RDP + "," + LDAPUtil.BASE_DN);
			String cn = LDAPUtil.getAttribute(attrs, "cn");
			String bdUid = LDAPUtil.getAttribute(attrs, "bduid");
			String departmentnumber = LDAPUtil.getAttribute(attrs, "bddepartmentid");
			String status = LDAPUtil.getAttribute(attrs, "status");
			String cerType = LDAPUtil.getAttribute(attrs, "certype");
			
			each.put("CN", cn);
			each.put("BD_UID", bdUid);
			each.put("DEPARTMENT", departmentnumber);
			each.put("STATUS", status);
			each.put("CER_TYPE", cerType);
			
			//TODO note that the certificate detail don't read from ldap server.
			each.put("VALIDITY_START_DATE", "2012-09-11");
			each.put("VALIDITY_END_DATE", "2013-09-11");
		} catch (Exception e) {
			throw new BizException(e);
		} finally {
			LDAPUtil.closeConnection();
		}
		return each;
	}
	
	/**
	 * Search all B/D certificate association record.
	 * @param param search criterion
	 * @return certificate association record.
	 */
	public List queryBDUserRegList(Map param) throws BizException  {
		
		String sessionUid = (String) param.get("SESSION_UID");
		if (sessionUid == null || "".equals(sessionUid)) {
			throw new BizException("Not found bd uid.");
		}
		List<Object> list = new ArrayList<Object>();
		Set<String> set = new HashSet<String>();
		
		try {
			SearchControls controls = new SearchControls();
			controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
			NamingEnumeration<SearchResult> answer = LDAPUtil.getDirContext().search(LDAPUtil.BD_CER_ASSOC_RDP + "," + LDAPUtil.BASE_DN, "bduid=" + sessionUid, controls);

			while (answer.hasMore()) {
				Map<String, String> each = new HashMap<String, String>();
				SearchResult result = (SearchResult) answer.next();
				System.out.println(result.getName());
				System.out.println(result.toString());
				Attributes attrs = result.getAttributes();
				String cn = LDAPUtil.getAttribute(attrs, "cn");
				String bdUid = LDAPUtil.getAttribute(attrs, "bduid");
				String departmentnumber = LDAPUtil.getAttribute(attrs, "bddepartmentid");
				String status = LDAPUtil.getAttribute(attrs, "status");
				String cerType = LDAPUtil.getAttribute(attrs, "certype");
				
				each.put("CN", cn);
				each.put("BD_UID", bdUid);
				each.put("DEPARTMENT", departmentnumber);
				each.put("STATUS", status);
				each.put("CER_TYPE", cerType);
				
				set.add(cerType);
				list.add(each);
			}
		} catch (Exception e) {
			throw new BizException(e);
		} finally {
			LDAPUtil.closeConnection();
		}
		
		checkCerTypeIsOrNotReg(list, set);
		return list;
	}

	private void checkCerTypeIsOrNotReg(List<Object> list, Set<String> set) {
		Map<String, String> each = null;
		
		if (!set.contains(SystemConst.CER_TYPE_HK_ORG)) {
			each = new HashMap<String, String>();
			each.put("CER_TYPE", SystemConst.CER_TYPE_HK_ORG);
			list.add(each);
		}
		
		if (!set.contains(SystemConst.CER_TYPE_HK_PERSONAL)) {
			each = new HashMap<String, String>();
			each.put("CER_TYPE", SystemConst.CER_TYPE_HK_PERSONAL);
			list.add(each);
		}
		
		if (!set.contains(SystemConst.CER_TYPE_DIGIT_ORG)) {
			each = new HashMap<String, String>();
			each.put("CER_TYPE", SystemConst.CER_TYPE_DIGIT_ORG);
			list.add(each);
		}
		
		if (!set.contains(SystemConst.CER_TYPE_DIGIT_PERSONAL)) {
			each = new HashMap<String, String>();
			each.put("CER_TYPE", SystemConst.CER_TYPE_DIGIT_PERSONAL);
			list.add(each);
		}
	}
	// insert a self-registration record.
	public void doInsertBDUserReg(Map param) throws BizException {
		
		String sessionUid = (String) param.get("SESSION_UID");
		String sessionUserName = (String) param.get("SESSION_USER_NAME");
		String departmentNumber = (String) param.get("SESSION_DEPARTMENT");
		String cerType = (String) param.get("CER_TYPE");
		String cerName = (String) param.get("CER_NAME");
		
		String cerAssocCN = sessionUid + "_" + cerType;
		String status = "Pending approval";
		
		Attributes attrs = new BasicAttributes();

		Attribute objclass = new BasicAttribute("objectclass");
		objclass.add("top");
		objclass.add("cspCerAssoc");
		attrs.put(objclass);
		
		LDAPUtil.putAttribute(attrs, "bduid", sessionUid);
		LDAPUtil.putAttribute(attrs, "bdusername", sessionUserName);
		LDAPUtil.putAttribute(attrs, "bddepartmentid", departmentNumber);
		LDAPUtil.putAttribute(attrs, "status", status);
		LDAPUtil.putAttribute(attrs, "certype", cerType);
		LDAPUtil.putAttribute(attrs, "certificatename", cerName);
		LDAPUtil.putAttribute(attrs, "validitystartdate", "2012-09-11");
		LDAPUtil.putAttribute(attrs, "validityenddate", "2013-09-11");
		System.out.println(attrs);
		try {
			LDAPUtil.getDirContext().bind("cn=" + cerAssocCN + "," + LDAPUtil.BD_CER_ASSOC_RDP + "," + LDAPUtil.BASE_DN, null, attrs);
		} catch (NamingException e) {
			e.printStackTrace();
			throw new BizException(e);
		} finally {
			LDAPUtil.closeConnection();
		}
	}
	
	/**
	 * Modify a B/D registration  info.
	 * @param param
	 * @throws BizException
	 */
	public void doUpdateBDUserReg(Map param) throws BizException {
		String cn = (String) param.get("CN");
		String sessionUserName = (String) param.get("SESSION_USER_NAME");
		String cerName = (String) param.get("CER_NAME");
		
		Attributes attrs = new BasicAttributes();

		LDAPUtil.putAttribute(attrs, "bdusername", sessionUserName);
		LDAPUtil.putAttribute(attrs, "status", SystemConst.STATUS_ACTIVATED);
		LDAPUtil.putAttribute(attrs, "certificatename", cerName);
		LDAPUtil.putAttribute(attrs, "validitystartdate", "2012-09-11");
		LDAPUtil.putAttribute(attrs, "validityenddate", "2013-09-11");
		System.out.println(attrs);
		try {
			LDAPUtil.getDirContext().modifyAttributes("cn=" + cn + "," + LDAPUtil.BD_CER_ASSOC_RDP + "," + LDAPUtil.BASE_DN, DirContext.REPLACE_ATTRIBUTE, attrs);
		} catch (NamingException e) {
			throw new BizException(e);
		} finally {
			LDAPUtil.closeConnection();
		}
	}
	
}